/*
** --------------------------------------------------------------------------
**
** Shp.h      -  This header file contains the public  data  structure
**               definitions  for the Element  Shape  Class  mechanism
**               within Pos3d.
**
** Description:  There are many conceptual operations which are common
**               to all types of elements. ( these operations include:
**               getting  element  shape faces,  computing  gauss-node 
**               extrapolation matrix, etc...).  In Pos3d, these types
**               of routines  stored  in a data  structure  called  an 
**               element  shape "class".  General  procedures  can  be 
**               written which will operate  properly  for all element
**               shape  classes currently in the system.
**
** Notes on implementation of this module:
**
**              The following variable  must be made available to  any
**              routines which call these methods:
**
**                ShapeClass  shape_class[NumShapeTypes];
**
**              This variable has been  bound ( currently  at run-time
**              when "shp_init ( )"  is called )  to the   appropriate
**              functions, e.g.:
**
**                shape_class[BRICK20].num_nodes = NumNodesB20()
**                shape_class[BRICK20].connectivity = ConnectivityB20()
**                ...
**
**              where "NumNodesB20 ( )" and "ShpConnectivity20 ( )" are
**              names  of functions  which are  specific  to  20-noded
**              bricks ( These functions reside in the file ShpBrk20.c ).
**
**
** --------------------------------------------------------------------------
**
** Created:  07-Jul-96   -   Luiz Fernando Martha
**      Stolen from Shape class of Femoop and modified.
**
** --------------------------------------------------------------------------
**
** Modified:  Novem/2000 - Antonio Miranda (amiranda)
**      Changed the input of method read (FILE -> int *conn)
**
** --------------------------------------------------------------------------
*/

#ifndef  _SHP_H
#define  _SHP_H

/*
**  -------------------------------------------------------------------------
**  Global definitions and symbols:
*/

#include <stdio.h>

#include "femdef.h"
#include "nfi.h"
// #include "gau.h"

/*
**  -------------------------------------------------------------------------
**  (Finite) Element Shape types:
*/
typedef enum _auxshapetype {

   UNDEF_SHAPE = -1,

   LINE2,          /*  2-noded line                           */
   LINE3,          /*  3-noded line                           */
   TRIA3,          /*  3-noded triangle                       */
   TRIA6,          /*  6-noded triangle                       */
   QUAD4,          /*  4-noded quadrilateral                  */
   QUAD8,          /*  8-noded quadrilateral                  */
   QUAD9,          /*  9-noded Lagrangean quadrilateral       */
 } AuxShapeType;


/*
**  -------------------------------------------------------------------------
**  Element Shape class (contains pointers to the methods):
*/

typedef struct _ShapeClass {

   void    (*init)            ( void );
   Telement_3d *(*New)             ( void );
   void    (*readresequence)  ( int * );
   void    (*resequence)      ( int * );
   void    (*getresequence)   ( int * );
   void    (*connectivity)    ( Telement_3d *, int * );
   void    (*derivmaprst)     ( Telement_3d *, NatCoord *, DerivNat * );
   void    (*derivshprst)     ( Telement_3d *, NatCoord *, DerivNat * );
   void    (*derivmap_i )     ( Telement_3d *, int, DerivNat ** );
   void    (*derivshp_i)      ( Telement_3d *, int, DerivNat ** );
   void    (*jacobian)        ( Telement_3d *, Tnode_data *, DerivNat *, 
                                double[3][3], double[3][3], double * );
   void    (*derivxyz)        ( Telement_3d *, double[3][3], DerivNat *,
                                DerivCart * );
   int     (*numgausspoint)   ( void ); 

   void    (*bmatrix)         ( Telement_3d *, DerivCart *, double **);

   double  (*gaussw_i)        ( Telement_3d *, int);
   void    (*gaussnatcoord_i) ( Telement_3d *, int, NatCoord *);

   int     (*dim)             ( Telement_3d * );
   void    (*free)            ( Telement_3d * );
   void    (*gausstonode)     ( Telement_3d *, double *, double * );
//   void    (*gausstype)       ( Telement_3d *, GaussType * );
   int     (*getfirstedge)    ( Telement_3d *, int *, int * );
   int     (*getnextedge)     ( Telement_3d *, int *, int * );
   int     (*getfirstface)    ( Telement_3d *, int *, int *);
   int     (*getnextface)     ( Telement_3d *, int *, int *);
   int     (*getshpedge)      ( Telement_3d *, int *, AuxShapeType *, int *, int * );
   int     (*getshpface)      ( Telement_3d *, int *, AuxShapeType *, int *, int * );
   void    (*getshpdomain)    ( Telement_3d *, ShapeType *, int *, int * );
   void    (*getverts)        ( Telement_3d *, int * );
   int     (*isinterface)     ( Telement_3d * );


   void    (*localsys)        ( Telement_3d *, int, DerivNat *, NodeCoord *,
                                double[3][3] );
   void    (*make)            ( Telement_3d *, int * );
   void    (*makedefault)     ( Telement_3d *, int * );
   void    (*mapfunc)         ( Telement_3d *, NatCoord *, ShapeVal * );
   void    (*nodalnatcoord)   ( Telement_3d *, NatCoord * );
   void    (*nodalcoord)      ( Telement_3d *, Tnode_data *, Tnode_data *);
   void    (*nodetovertex)    ( Telement_3d *, double *, double * );
   int     (*nummapnodes)     ( Telement_3d * );
   int     (*numshpnodes)     ( Telement_3d * );
   int     (*numverts)        ( Telement_3d * );
   void    (*print)           ( Telement_3d * );
   int     (*read)            ( Telement_3d *, int * );
   void    (*shapefunc)       ( Telement_3d *, NatCoord *, ShapeVal * );
   void    (*shapefunc_i)     ( Telement_3d *, int , ShapeVal ** );

   double  (*sizeerror)       (  Telement_3d *, Tnode_data *, double );

} ShapeClass;

/*
**  -------------------------------------------------------------------------
**
**  Here follows a generic description of the methods:
**
**  --------------------------- class methods -------------------------------
**
**  init          - initializes subclass.
**  new           - creates a new element shape of given class.
**  readresequence- reads resequence vector for element shape node numbering.
**  resequence    - resequences element shape node numbering.
**  getresequence - gets resequence vector for element shape node numbering.
**
**  ------------------------- instance methods ------------------------------
**
**  connectivity  - returns element shape connectivity.
**  derivmaprst   - returns the derivatives of interpolation functions
**                  at geometric nodes in local coordinate system.
**  derivshprst   - returns the derivatives of interpolation functions
**                  at shape nodes in local coordinate system.
**  derivxyz      - returns the derivatives of interpolation functions
**                  at shape nodes in global coordinate system.
**  dim           - returns shape dimension (1D, 2D, or 3D).
**  free          - releases all memory used by element shape.
**  gausstonode   - extrapolates from Gauss points' responses to nodal 
**                  responses.
**  gausstype     - returns Gauss sub-class type which is consistent with
**                  element shape.
**  getfirstedge  - get no. of vertices and vertex indices of first
**                  edge of given shape.
**  getnextedge   - get no. of vertices and vertex indices of next
**                  edge of given shape (returns false (0) if no more edges).
**  getfirstface  - get no. of vertices and vertex indices of first
**                  face of given shape.
**  getnextface   - get no. of vertices and vertex indices of next
**                  face of given shape (returns false (0) if no more faces).
**  getshpedge    - get shape type, no. of nodes, and connectivity of an 
**                  edge of given shape for a given pair of corner nodes.
**  getshpface    - get shape type, no. of nodes, and connectivity of a 
**                  face of given shape for a given pair of corner nodes and
**                  a third node defining the face normal direction.
**  getshpdomain  - get shape type, no. of nodes, and connectivity of
**                  of given shape.
**  getverts      - get no. of topological vertices and vertex indices of 
**                  given shape.
**  isinterface   - returns a true status if shape object corresponds to 
**                  an interface finite element (discontinuous) and returns
**                  a false status if it is a continuous element.
**  jacobian      - returns the Jacobian matrix, its inverse and its
**                  determinant.
**  localsys      - get rotation matrix of local system w.r.t. global axes
**                  at a given point given by its parametric coordinates.
**  make          - makes a element shape from a given connectivity
**                  (connectivity is ordered according to the class node 
**                   resequencing data).
**  makedefault   - makes a element shape from a given connectivity
**                  (the connectivity is assumed in the default class sequence).
**  mapfunc       - returns the geometric interpolation functions
**                  evaluated at a given point in local coordinates.
**  nodalnatcoord - returns the natural coordinates of the nodes of
**                  the given element shape.
**  nodalcoord    - returns the Cartesian coordinates of the  nodes of
**                  the given element shape.
**  nodetovertex  -  extrapolates from fem nodal responses to topological  
**                  vertex responses.
**  nummapnodes   - returns the number of nodes in element shape used
**                  to interpolate (map) its geometry.
**  numshpnodes   - returns the number of nodes used  by  shape inter-
**                  polation functions.
**  numverts      - returns the number of topological vertices (take into 
**                  account nodal repetition or non-existing mid-edge nodes).
**  print         - prints element shape data.
**  read          - fill element shape data with data read from a given
**                  connectivity vector.
**  shapefunc     - returns the shape interpolation functions
**                  evaluated at a given point in local coordinates.
**
*/

/*
**  -------------------------------------------------------------------------
**  Public data and functions:
*/

#ifdef _SHP_CPP

ShapeClass  shape_class[NumShapeTypes];
void        shp_init             ( void );
void        shp_free             ( void );
void        shp_freeshape        ( Telement_3d * );
void        shp_gausstonode      ( Telement_3d *, double *, double * );
void        shp_nodetovertex     ( Telement_3d *, double *, double * );
int         shp_isinterface      ( Telement_3d * );
void        shp_jacobian         ( Telement_3d *shp, Tnode_data *coord, DerivNat *deriv_rst, 
                                   double jac[3][3], double invjac[3][3], double *det);
void        shp_derivXYZ         ( Telement_3d *shp, double invjac[3][3], 
                                   DerivNat *derivshp_rst, DerivCart *deriv_xyz );
void        shp_BMatrix          ( Telement_3d *shp, DerivCart *deriv_xyz,
                                   double **b_matrix);
void        shp_NodalCoord       ( Telement_3d *shp, Tnode_data *node_coords, 
                                   Tnode_data *coord );


#else

extern ShapeClass  shape_class[];
extern void        shp_init             ( void );
extern void        shp_free             ( void );
extern void        shp_freeshape        ( Telement_3d * );
extern void        shp_gausstonode      ( Telement_3d *, double *, double * );
extern void        shp_nodetovertex     ( Telement_3d *, double *, double * );
extern int         shp_isinterface      ( Telement_3d * );
extern void        shp_jacobian         ( Telement_3d *shp, Tnode_data *coord, DerivNat *deriv_rst, 
                                          double jac[3][3], double invjac[3][3], double *det);
extern void        shp_derivXYZ         ( Telement_3d *shp, double invjac[3][3], 
                                          DerivNat *derivshp_rst, DerivCart *deriv_xyz );
extern void        shp_BMatrix          ( Telement_3d *shp, DerivCart *deriv_xyz,
                                          double **b_matrix);
extern void        shp_NodalCoord       ( Telement_3d *shp, Tnode_data *node_coords, 
                                          Tnode_data *coord );

#endif

/* Some definitions for method functions not used currently.
 */
#define shp_derivxyzarea    0L
#define shp_derivxyzsolid   0L
#define shp_jacobianarea    0L
#define shp_jacobiansolid   0L
#define shp_localsysarea    0L
#define shp_localsyssolid   0L
#define shp_nodalcoord      0L
#define shp_printshape      0L



/*
**  -------------------------------------------------------------------------
**  Auxiliar methods
*/
void ShpMathInver3x3 (double jac[3][3], double invjac[3][3], double *det);


/*
**  -------------------------------------------------------------------------
**  Macros to call the methods
*/

#define ShpInit(type)                                      \
        if(shape_class[type].init != 0L)                   \
          (*shape_class[type].init)()

#define ShpNew(type)                                       \
          (*shape_class[type].New)()

#define ShpReadResequence(type,fd)                         \
        if(shape_class[type].readresequence != 0L)         \
          (*shape_class[type].readresequence)(fd)

#define ShpResequence(type,r)                              \
        if(shape_class[type].resequence != 0L)             \
          (*shape_class[type].resequence)(r)

#define ShpGetResequence(type,r)                           \
        if(shape_class[type].getresequence != 0L)          \
          (*shape_class[type].getresequence)(r)

#define ShpConnectivity(els,cn)                            \
        (*shape_class[els->type].connectivity)(els,cn)

#define ShpDerivMaprst(els,gr,dr)                          \
        (*shape_class[els->type].derivmaprst)(els,gr,dr)

#define ShpDerivShprst(els,gr,dr)                          \
        (*shape_class[els->type].derivshprst)(els,gr,dr)

#define ShpDerivMap_i(els,gr,dr)                          \
        (*shape_class[els->type].derivmap_i)(els,gr,dr)

#define ShpDerivShp_i(els,gr,dr)                          \
        (*shape_class[els->type].derivshp_i)(els,gr,dr)

#define ShpDerivxyz(els,ji,dr,dx)                       \
        (*shape_class[els->type].derivxyz)(els,ji,dr,dx)

#define ShpNumGaussPoint(els)                             \
        (*shape_class[els->type].numgausspoint)() 

#define ShpBMatrix(els,dx,b)                              \
        (*shape_class[els->type].bmatrix) (els,dx,b)

#define ShpGaussWgt(els,i)                              \
        (*shape_class[els->type].gaussw_i) (els,i)

#define ShpGaussNatCoord(els,i,b)                              \
        (*shape_class[els->type].gaussnatcoord_i) (els,i,b)

#define ShpDim(els)                                        \
        (*shape_class[els->type].dim)(els)

#define ShpFree(els)                                       \
        (*shape_class[els->type].free)(els)

#define ShpGauss(els)                                      \
        (els->gauss)

#define ShpGaussToNode(els,gr,nr)                          \
        (*shape_class[els->type].gausstonode)(els,gr,nr)

#define ShpGaussType(els,gt)                               \
        (*shape_class[els->type].gausstype)(els,gt)

#define ShpGetFirstEdge(els,n,vi)                          \
        (*shape_class[els->type].getfirstedge)(els,n,vi)

#define ShpGetNextEdge(els,n,vi)                           \
        (*shape_class[els->type].getnextedge)(els,n,vi)

#define ShpGetFirstFace(els,n,vi)                          \
        (*shape_class[els->type].getfirstface)(els,n,vi)

#define ShpGetNextFace(els,n,vi)                           \
        (*shape_class[els->type].getnextface)(els,n,vi)

#define ShpGetShapeEdge(els,cr,st,n,cn)                    \
        (*shape_class[els->type].getshpedge)(els,cr,st,n,cn)

#define ShpGetShapeFace(els,cr,st,n,cn)                    \
        (*shape_class[els->type].getshpface)(els,cr,st,n,cn)

#define ShpGetShapeDomain(els,st,n,cn)                     \
        (*shape_class[els->type].getshpdomain)(els,st,n,cn)

#define ShpGetVerts(els,vi)                                \
        (*shape_class[els->type].getverts)(els,vi)

#define ShpIsInterface(els)                                \
        (*shape_class[els->type].isinterface)(els)

#define ShpJacobian(els,coord,dr,j,ji,d)                      \
        (*shape_class[els->type].jacobian)(els,coord,dr,j,ji,d)

#define ShpLocalSys(els,nm,dr,c,rm)                        \
        (*shape_class[els->type].localsys)(els,nm,dr,c,rm)

#define ShpMake(els,cn)                                    \
        (*shape_class[els->type].make)(els,cn)

#define ShpMakeDefault(els,cn)                             \
        (*shape_class[els->type].makedefault)(els,cn)

#define ShpMapFunc(els,co,sv)                              \
        (*shape_class[els->type].mapfunc)(els,co,sv)

#define ShpNodalNatCoord(els,c)                            \
        (*shape_class[els->type].nodalnatcoord)(els,c)

#define ShpNodalCoord(els,c,lc)                               \
        (*shape_class[els->type].nodalcoord)(els,c,lc)

#define ShpNodeToVertex(els,nr,vr)                         \
        (*shape_class[els->type].nodetovertex)(els,nr,vr)

#define ShpNumMapNodes(els)                                \
        (*shape_class[els->type].nummapnodes)(els)

#define ShpNumShpNodes(els)                                \
        (*shape_class[els->type].numshpnodes)(els)

#define ShpNumVerts(els)                                   \
        (*shape_class[els->type].numverts)(els)

#define ShpPrint(els)                                      \
        (*shape_class[els->type].print)(els)

#define ShpRead(els,fd)                                    \
        (*shape_class[els->type].read)(els,fd)

#define ShpShapeFunc(els,co,sv)                            \
        (*shape_class[els->type].shapefunc)(els,co,sv)

#define ShpShapeFunc_i(els,co,sv)                            \
        (*shape_class[els->type].shapefunc_i)(els,co,sv)

#define ShpType(els)                                       \
        (els->type)

#define ShpNewSizeError(els,c,re)                               \
        (*shape_class[els->type].sizeerror)(els,c,re)


#endif
